package com.cskaoyan.javase.object._5finlize;

import java.util.Scanner;

/**
 * 1.方法的声明
 * finalize方法的声明和方法体比较简单，如下：
 * protected void finalize() throws Throwable { }
 * 首先注意访问权限是protected，这说明在不重写访问权限的情况下，仅能够在自身类中创建自身对象，才能调用这个方法。
 *
 * 其次它的方法体是空的，功能没有实现，这种设计的目的是为了让子类自己去重写该方法的实现。这种做法比起抽象方法的强制子类实现，要更加灵活，而且可以用在普通类中。
 *
 * 最后，它的方法声明中有一个throws Throwable， 这是方法抛出异常列表的声明，现在不用管它，后面会讲。
 *
 *
 * 2.方法的作用
 * finalize方法是Java沿用的C++中的析构函数的设计。
 * 在C++当中，负责对象的生命周期的，有两个函数：
 * 构造函数，用来在对象"出生"时，给成员变量赋值，在Java当中对应构造器。
 * 析构函数，用来在对象销毁时，给对象的死亡做"善后"工作，在Java中就对应finalize方法。
 * 所以要搞明白finalize方法的作用，就要搞清楚析构函数的作用，理解何为对象死亡的"善后"工作。
 *
 * 一个对象在内存中存在,普遍占用两种资源:
 *      1.对象本身作为一种存储结构所占用的资源.这个内存在对象销毁时就会随之释放。
 *      这个释放的过程在不同的语言当中，形式是不同的，比如C++是程序员手动释放的，Java依赖是GC自动完成释放。
 *      但不管是什么形式，这些对象所占用的内存都是可以准确释放的。
 *
 *      2.对象在存在时，很多时候不仅自身要占用内存，还可以需要去使用一些系统资源，占用一些系统资源，比如：
 *             a.做I/O操作时，需要占用系统的I/O资源。
 *             b.做网络操作，要占用网络资源。
 *              ...
 *        那么这些系统资源，在对象使用后，也要被释放掉，不然就会一直被占用，可能就会产生不良问题。
 *        C++当中的析构函数就是完成这个功能的。
 *        程序员将释放资源的语句写进析构函数中，在对象销毁时，该函数自动被调用，自动去释放对象占用的系统资源。
 *        析构函数之所以能够起作用,因为C++的对象回收是手动的
 *
 *        Java当中的finalize方法就是"模仿"析构函数设计的，finalize方法也会在对象销毁时自动被调用，我们Java程序员只需要把释放资源的代码放在finalize方法中，就可以完成对象销毁的"善后"工作。
 *        这里就体现了Java GC自动垃圾回收的缺点：程序员缺乏对对象销毁的控制，对象的垃圾回收具有不确定性，没有时效性。
 *        那么连带着finalize方法的执行也是不确定的。
 *        在这段不确定长度的时间里，对象其实早就已经没用了，但系统资源还是一直被占用着，造成资源的浪费。
 *        显然释放系统资源这么一件重要的事情，不能依赖于一个不稳定的机制。
 * 从Java9开始，Java官方正式将该方法标记为@Deprecated，表示这个方法已经被放弃使用了。
 * 所以Java当中释放对象占用额外系统资源的操作,需要程序员完全手动实现(但是好在这种对象不多)
 *
 * @since 16:07
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str = sc.nextLine();
        System.out.println(str);
        // 标准操作是要关闭的
        sc.close();
        // sc.nextLine();*/
        new Student();
        // 通知GC进行垃圾回收
        System.gc();
    }
}

class Student {
    public void test() throws Throwable {
        this.finalize();
    }

    public static void testStatic() throws Throwable {
        new Student().finalize();
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("模拟释放系统资源~~~");
    }
}